package com.mlnx.ecg.ui.panels;

import com.mlnx.ecg.ui.config.ECGConfig;
import com.mlnx.ecg.ui.config.ECGDeviceConstant;
import com.mlnx.ecg.ui.databuffer.HistoryEcgDatabuffer;
import com.mlnx.ecg.ui.databuffer.TimeEcgData;
import com.mlnx.ecg.ui.model.Channel;
import com.mlnx.ecg.ui.model.RectF;
import com.mlnx.ecg.ui.model.TimePoint;
import com.mlnx.ecg.ui.model.WavePos;
import com.mlnx.ecg.ui.style.WaveStyle;
import com.mlnx.ecg.ui.view.TimeWaveView;
import com.mlnx.ecg.ui.view.WaveView;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

public class HistoryEcgPanel extends JPanel {
    private String[] MINUTE_STR = new String[]{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",};

    private List<WaveView> waveViews = new ArrayList<>();

    private boolean showGridding = true;

    private EcgShowType ecgShowType;

    private List<List<Object>> bufferList;

    private int start = 0;

    private JSlider slider;

    private JLabel startLabel, endLabel;

    private HistoryEcgDatabuffer historyEcgDatabuffer;

    private Channel channel;

    private Long currTime;

    public HistoryEcgPanel(Integer secondBuffer, List<TimeEcgData> timeEcgData,
                           EcgShowType ecgShowType) {
        super();
        historyEcgDatabuffer = new HistoryEcgDatabuffer(secondBuffer, timeEcgData);
        this.bufferList = historyEcgDatabuffer.getBufferList();
        this.ecgShowType = ecgShowType;

        setLayout(new BorderLayout());

        JPanel bottom = new JPanel(new BorderLayout());
        bottom.setPreferredSize(new Dimension(0, 100));
        {
            JPanel p = new JPanel(new GridLayout(1, 1));
            p.setBorder(new EmptyBorder(40, 50, 0, 50));
            {
                slider = new JSlider();
                slider.setMinimum(0);
                slider.setMaximum(secondBuffer);
                slider.setValue(0);

                p.add(slider);
            }
            bottom.add(p, BorderLayout.CENTER);

            p = new JPanel(new BorderLayout());
            p.setBorder(new EmptyBorder(0, 50, 0, 50));
            p.setPreferredSize(new Dimension(0, 30));
            {
                startLabel = new JLabel("00:00");
                startLabel.setForeground(new Color(40, 40, 40));
                startLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
                p.add(startLabel, BorderLayout.WEST);

                endLabel = new JLabel(MINUTE_STR[secondBuffer / 60] + ":" + MINUTE_STR[secondBuffer % 60]);
                endLabel.setForeground(new Color(40, 40, 40));
                endLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
                p.add(endLabel, BorderLayout.EAST);
            }
            bottom.add(p, BorderLayout.SOUTH);

        }
        add(bottom, BorderLayout.SOUTH);

        addListeners();
    }

    private void addListeners() {
        addComponentListener(new EcgComponentListener());

        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                Integer rotation = e.getWheelRotation();
                slider.setValue(slider.getValue() + rotation);

            }
        });

        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                startLabel.setText(MINUTE_STR[slider.getValue() / 60] + ":" + MINUTE_STR[slider.getValue() % 60]);

                start = slider.getValue() * ECGConfig.SAMPLING;
                move();


            }
        });
    }

    public void clearChosenArea() {
        for (WaveView waveView : waveViews) {

            TimeWaveView timeWaveView = (TimeWaveView) waveView;

            timeWaveView.clearChoseTimePoints();
        }
    }

    // 波形前滚或者后滚
    public void move() {
        if (bufferList == null || bufferList.size() <= 0)
            return;

        if (start < 0)
            start = 0;

        if (start > bufferList.get(0).size()
                - waveViews.get(0).getMaxNumOfPoints())
            start = bufferList.get(0).size()
                    - waveViews.get(0).getMaxNumOfPoints();


        clearChosenArea();

        loadData(start);
        refreshUI();
    }

    private synchronized void initWaveView() {

        if (getHeight() == 0 || getWidth() == 0)
            return;

        setEcgShowType(ecgShowType);

        loadData(start);
        refreshUI();
    }

    public void refreshUI() {
        repaint();
        updateUI();
    }

    public synchronized void setShowGridding(boolean showGridding) {
        this.showGridding = showGridding;

        if (waveViews != null && waveViews.size() > 0) {
            for (WaveView waveView : waveViews) {
                waveView.setShowGridding(showGridding);
            }
        }
    }

    public synchronized void setEcgShowType(EcgShowType ecgShowType) {
        this.ecgShowType = ecgShowType;

        waveViews.clear();

        if (ecgShowType.equals(EcgShowType._1x1)) {
            ecgShowType = EcgShowType._1x12;
        }

        for (int i = 0; i < 12; ++i) {
            WaveView waveView = new TimeWaveView(EcgShowType.getWavePos(
                    ecgShowType, i, getWidth(), getHeight() - 100), i,
                    ECGConfig.ECGLEADNAMES.get(i), ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);
            waveView.setShowGridding(showGridding);

            waveViews.add(waveView);

        }

        if (ecgShowType.equals(EcgShowType._4x3)) {
            WaveView waveView = new TimeWaveView(EcgShowType.getWavePos(
                    this.ecgShowType, -1, getWidth(), getHeight() - 100), 0,
                    ECGConfig.ECGLEADNAMES.get(0), ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);

            waveView.setShowGridding(showGridding);
            waveViews.add(waveView);
        }

        if (this.ecgShowType.equals(EcgShowType._1x1)) {
            Channel channel = new Channel();
            channel.setChannelFlag(new boolean[]{true, false, false, false,
                    false, false, false, false, false, false, false, false});
            setChannel(channel);
        }

        if (ecgShowType.equals(EcgShowType._1x7)) {
            Channel channel = new Channel();
            channel.setChannelFlag(new boolean[]{true, true, true, true,
                    true, true, true, false, false, false, false, false});
            setChannel(channel);
        }
    }

    public synchronized void setChannel(Channel channel) {

        this.channel = channel;

        waveViews.clear();

        List<WavePos> wavePoss = EcgShowType.getWavePos(channel, getWidth(),
                getHeight() - 100);
        List<Integer> list = channel.getSelectChannelFlag();
        for (int i = 0; i < list.size(); i++) {
            String ecgLeadName = ECGConfig.ECGLEADNAMES.get(list.get(i));
            if (channel.isvLeadAsV5() && ecgShowType.equals(EcgShowType._1x7)
                    && i == 6) {
                ecgLeadName = "V5";
            }

            WaveView waveView = new TimeWaveView(wavePoss.get(i), list.get(i),
                    ecgLeadName, ECGConfig.SAMPLING, ECGDeviceConstant.DEFAULT_SCALE, ECGDeviceConstant.DEFAULT_SPEED);
            waveView.setShowGridding(showGridding);
            waveViews.add(waveView);
        }
    }

    public Long getCurrPacketTime() {
        return currTime;
    }

    public void loadData(int start) {
        if (bufferList == null || bufferList.size() <= 0)
            return;

        boolean first = true;

        synchronized (HistoryEcgPanel.this) {

            if (waveViews != null && waveViews.size() > 0) {

                for (WaveView waveView : waveViews) {
                    waveView.earsePoints();
                }

                for (int i = start, j = 0; j < waveViews.get(0)
                        .getMaxNumOfPoints(); i++, j++) {

                    for (WaveView waveView : waveViews) {

                        if (bufferList.get(waveView.getFlag()).size() > i) {

                            try {
                                HistoryECGData data = (HistoryECGData) bufferList
                                        .get(waveView.getFlag()).get(i);

                                if (data == null) {
                                    break;
                                }

                                if (first) {
                                    currTime = data.getPacketTime();
                                    first = !first;
                                }

                                ((TimeWaveView) waveView).updatePoint(
                                        data.getValue(), data.getPacketTime(),
                                        data.getNumber() + "");
                            } catch (ArrayIndexOutOfBoundsException e) {
                                break;
                            }
                        }

                    }
                }
            }
        }
        repaint();
    }

    @Override
    public synchronized void paint(Graphics g) {
        super.paint(g);

        if (waveViews != null && waveViews.size() > 0) {
            for (WaveView waveView : waveViews) {
                waveView.doDraw((Graphics2D) g, false, WaveStyle.BG_COLOR,
                        WaveStyle.FRAME_COLOR, WaveStyle.TEXT_COLOR,
                        WaveStyle.ECG_COLOR);
            }
        }
    }

    class EcgComponentListener implements ComponentListener {

        @Override
        public void componentResized(ComponentEvent e) {
            initWaveView();
        }

        @Override
        public void componentMoved(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void componentShown(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void componentHidden(ComponentEvent e) {
            // TODO Auto-generated method stub

        }

    }

}
